#include <thread>
#include "stream_server_rtsp.h"
#include "stream_server_source.h"
#include "stream_server_g711a.h"
#include "base_log.h"

namespace El {
namespace StreamServer {

CRtspServer &CRtspServer::GetInstance()
{
    static CRtspServer instance;
    return instance;
}

bool CRtspServer::Start()
{
    scheduler = BasicTaskScheduler::createNew();
    env = BasicUsageEnvironment::createNew(*scheduler);

    UserAuthenticationDatabase *authDB = nullptr;
#if 0
    // Uncomment this block if you want to add authentication
    authDB = new UserAuthenticationDatabase;
    authDB->addUserRecord("username1", "password1");
#endif

    OutPacketBuffer::maxSize = 100000; // Adjust as needed

    int32_t port = 8554;
    rtspServer = RTSPServer::createNew(*env, port, authDB);
    if (rtspServer == nullptr) {
        LOG_ERROR("Failed to create RTSP server on port {}: {}", port, env->getResultMsg());
        return false;
    }

    char const *descriptionString = "RTSP Server powered by Live555";

    // Add a new "live" RTSP server:
    ServerMediaSession *sms = ServerMediaSession::createNew(*env, "live", "live", descriptionString);
    sms->addSubsession(StreamServerMediaSubsession::createNew(*env, 0, 0, false));
    sms->addSubsession(G711aAudioSubsession::createNew(*env, 0, 0, False));
    rtspServer->addServerMediaSession(sms);

    LOG_INFO("RTSP URL: {}", rtspServer->rtspURL(sms));

    // Create a thread to run the event loop
    std::thread eventLoopThread([this]() {
        env->taskScheduler().doEventLoop(); // does not return
    });
    eventLoopThread.detach();

    return true;
}

void CRtspServer::Stop()
{
    if (rtspServer) {
        Medium::close(rtspServer);
        rtspServer = nullptr;
    }
    if (env) {
        env->reclaim();
        env = nullptr;
    }
    if (scheduler) {
        delete scheduler;
        scheduler = nullptr;
    }
}

} // namespace StreamServer
} // namespace El